#ifndef _FXG_COMMON_MODULE_
#define _FXG_COMMON_MODULE_

#include "../fxcrt/fx_basic.h"
#include "../fxge/fx_ge.h"

/**
 * @name Filter type
 */
/*@{*/
#define FXG_FILTERTYPE_PAINT			FXBSTR_ID('P', 'I', 'N', 'T')	/**< Indicate paint filter */
/*@}*/

/**
 * @name Filter rendering status
 */
/*@{*/
#define FXG_FILTER_RENDER_READY				1	/**< Indicate the filter is ready for render. */
#define FXG_FILTER_RENDER_TOBECONTINUE		2	/**< Indicate the filter must be continue. */
#define FXG_FILTER_RENDER_FINISH			3	/**< Indicate the filter has finished rendering. */
#define FXG_FILTER_RENDER_ERROR_MEMORY		4	/**< Indicate the filter is out of memory. */
/*@}*/

/**
 * @name The color space supported now.
 */
/*@{*/
#define FXG_CS_DeviceGray					1	/**< Indicate the color in device Gray. */
#define FXG_CS_DeviceRGB					2	/**< Indicate the color in device RGB. */
#define FXG_CS_DeviceCMYK					3	/**< Indicate the color in device CMYK. */
/*@}*/

/** @brief Structure of the color used in canvas. */
typedef struct 
{
	FX_INT32					m_nCs;			/**< Defined above, FXG_CS_XXX. */ 
	CFX_ArrayTemplate<FX_FLOAT>	m_Data;			/**< The size indicate the components, if Cs Gray and Comps 2, indicate alpha channel exist. */
} FXG_Color;

/** 
 * @brief Filter notify interface.
 * If the application needs to control real-time flush, you need to implement the interface.
 */
class IFXG_FilterNotify
{
public:
	/** 
	 * @brief The flush method.
	 *
	 * @param[in] rect	The rect should be flush.
	 */
	virtual void				Flush(const FX_RECT& rect) = 0;
};

/** 
 * @brief The canvas interface. A container that can hold DIB and do a lot of other operations.
 */
class IFXG_Canvas
{
public:
	/**
	 * Create a canvas.
	 */
	static	IFXG_Canvas*		Create();

	/**
	 * Destroy the current canvas.
	 */
	virtual void				Destroy() = 0;

	/**
	 * Set the filter notify.
	 * Required if the application needs to control real-time flush.
	 *
	 * @param[in] pNotify		The notify will be invoked multiple times when rendering.
	 */
	virtual void				SetFilterNotify(IFXG_FilterNotify* pNotify) = 0;

	/**
	 * Attach an existing bitmap to the canvas.
	 * Required if CreateLayer does not used.
	 *
	 * @param[in] pBitmap		The bitmap to be attached.
	 */
	virtual void				AttachLayer(CFX_DIBitmap* pBitmap) = 0;

	/**
	 * Create a new bitmap and attach to the canvas. 
	 * The bitmap will be destroyed when the canvas destructs.
	 * Required if AttachLayer does not used.
	 *
	 * @param[in] nWidth		The bitmap width.
	 * @param[in] nHeight		The bitmap height.
	 * @param[in] format		The bitmap format.
	 * @return FALSE if creation failed (OOM), or TRUE if success.
	 */
	virtual FX_BOOL				CreateLayer(FX_INT32 nWidth, FX_INT32 nHeight, FXDIB_Format format) = 0;

	/**
	 * Set the clip region
	 * OPTION. If the region does not set, the canvas will use the whole layer size as default clip region.
	 *
	 * @param[in] pClipRgn		Set the clip region to the canvas.
	 */
	virtual void				SetClipRgn(CFX_ClipRgn* pClipRgn) = 0;

	/**
	 * Set the foreground color
	 * OPTION. If the color does not set, the canvas will use black as foreground color
	 *
	 * @param[in] pColor		Set the foreground color of canvas.
	 */
	virtual void				SetFGColor(const FXG_Color* pColor) = 0;

	/**
	 * Set the background color
	 * OPTION. If the color does not set, the canvas will use black as background color
	 *
	 * @param[in] pColor		Set the background color of canvas.
	 */
	virtual void				SetBGColor(const FXG_Color* pColor) = 0;

	/**
	 * Set the active channel of the canvas. Reserved now.
	 * OPTION. If the color does not set, default all channels active, 
	 * otherwise, the filter process only active channel.
	 *
	 * @param[in] pColor		Set the background color of canvas.
	 */
	virtual void	            SetActiveChannel(FX_INT32 nChannel) = 0;
	
	/** Get current filter notify if exist. */
	virtual IFXG_FilterNotify*  GetFilterNotify() = 0;

	/** Get current layer if exist. */
	virtual CFX_DIBitmap*       GetLayer() = 0;

	/** Get current clip region if exist. */
	virtual CFX_ClipRgn*		GetClipRgn() = 0;

	/** Get current foreground color. */
	virtual const FXG_Color*	GetFGColor() = 0;

	/** Get current background color. */
	virtual const FXG_Color*	GetBGColor() = 0;

	/** Get current active channel, if -1 indicate that all channels active. Reserved now. */
	virtual FX_INT32            GetActiveChannel() const = 0;
};

/** 
 * @brief The filter interface. Can be FXG_FILTERTYPE_PAINT or more. 
 */
class IFXG_Filter
{
public:
	/**
	 * Get the filter type defined in FXG_FILTERTYPE_XXX 
	 *
	 * @return The filter type
	 */
	virtual FX_INT32			GetFilterType() const = 0;

	/**
	 * Associated filter and canvas.
	 *
	 * @param[in] pCanvas		The canvas to be associated with the filter.
	 */
	virtual void				SetCanvas(IFXG_Canvas* pCanvas) = 0;

	/** 
	 * Get the associated canvas if exist. 
	 *
	 * @return A pointer to IFXG_Canvas.
	 */
	virtual IFXG_Canvas*		GetCanvas() = 0;

	/** 
	 * Prepare the filter. 
	 *
	 * @return TRUE indicate success, otherwise failure.
	 */
	virtual FX_BOOL				Prepare() = 0;

	/** 
	 * If the filter is ready by Prepare, then we can start rendering 
	 *
	 * @return Flag defined above, FXG_FILTER_RENDER_XXX
	 */
	virtual FX_INT32			Render(IFX_Pause* pPause = NULL) = 0;
};

/**@brief Advanced color management interface. Reserved now. */
class IFXG_Color 
{
public:
	virtual void SetProfile(FX_INT32 nCS, FX_LPCBYTE pBuffer, FX_DWORD dwSize) = 0;
	virtual void SetRgb(FX_ARGB argb) = 0;
	virtual void SetCmyk(FX_CMYK cmyk, FX_BYTE alpha) = 0;

	virtual void GetRgb(FX_ARGB& argb) = 0;
	virtual void GetCmyk(FX_CMYK& cmyk, FX_BYTE& alpha) = 0;
	virtual void GetGray(FX_BYTE& gray, FX_BYTE& alpha) = 0;
};

#endif // _FXG_COMMON_MODULE_